package com.hxbd.test.utils;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import org.testng.Assert;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hxbd.service.JsonArrayCompareService;
import com.hxbd.test.Beans.TResult;


public class JsonArrayCompare implements JsonArrayCompareService{
	private JSONArray o;
	private TResult tresult;
//	public JsonArrayCompare () {
//		
//	}
	public JsonArrayCompare (String json) {
		o = JSON.parseArray(json);
		tresult = new TResult();
	}
	/**
	 * 包含某字符串
	 * 示例：contains(truckno,123)
	 * @param key
	 * @param value
	 * @return Boolean
	 */
	public TResult contains (String str) {
		Boolean tmp = true;
		 for (Object obj : o) {
			 if (!((JSONObject)obj).toString().contains(str)) {
				 tmp = false;
				 tresult.setErrData(obj.toString());
				 break;
			 }
		 }
		tresult.setResult(tmp);
		return tresult;
	}
	//= != < > <= >= contains() notContains() startWith endWith notNull isNull between notBetween in notIn
	/**
	 * key包含某值
	 * 示例：contains(truckno,123)
	 * @param key
	 * @param value
	 * @return Boolean
	 */
	public TResult contains (String key, String value) {
		Boolean tmp = true;
		 for (Object obj : o) {
			 if (!((JSONObject)obj).containsKey(key)) {
				 Assert.fail("返回数据:"+obj.toString()+"不包含参数:"+key);
			 }
			 if (!((JSONObject)obj).getString(key).contains(value)) {
				 tmp = false;
				 tresult.setErrData(obj.toString());
				 break;
			 }
		 }
		tresult.setResult(tmp);
		return tresult;
	}
	
	/**
	 * 返回reslut包含某字符串,有标点符号,的时候用{}或者[]或者''把参数括起来
	 * @param result
	 * @return
	 */
	public Boolean containsRs(String result) {
		return o.toString().contains(result);
	}

	/**
	 * 返回数据包含多个字符串(只支持jsonArray)
	 * 示例：containsAllStr('"carNumber":"沪A0V652","driverName":"lucy"','"carNumber":"沪A21312","driverName":"duan"')
	 * 每个字符串放在单引号中,多个字符串以,分隔
	 * @param valueStr
	 * @return 
	 */
	public TResult containsAllStr (String ...valueStr) {
		tresult.setResult(true);
		JSONArray Ja_copy = new JSONArray();
		Ja_copy.addAll(o);
		for1:
		for (String str : valueStr) {
			Boolean bol = false;
			for2:
			for (int i = 0; i < Ja_copy.size(); i++) {					
				if (Ja_copy.get(i).toString().contains(str)) {
					bol = true;					
					Ja_copy.remove(i);
					break for2;
				}
			}
			if (!bol) {	
				tresult.setResult(false);
				tresult.setErrData("接口返回数据:"+o.toString()+"找不到一条包含:"+str+"的数据");
				break for1;
			}
		}
		return tresult;
	}
	/**
	 * 返回数据包含多个符合条件的参数及其值(只支持jsonarray)
	 * 示例：containsAllParams('"driverName":"lucy","carNumber":"沪A0V652"','"carNumber":"沪A21312","driverName":"duan"')
	 * 每个字符串放在单引号中,多个字符串以,分隔
	 * @param params
	 */
	public TResult containsAllParams(String ...params) {
		tresult.setResult(true);
		JSONArray Ja_copy = new JSONArray();
		Ja_copy.addAll(o);
		for1:
		for (String str : params) {
			String []param = str.split(",");
			Boolean bol1 = false;
			for2:
			for (int i = 0; i < Ja_copy.size(); i++) {
				Boolean bol2 = true;
				for (String str2 : param) {
					if (!Ja_copy.get(i).toString().contains(str2)) {
						bol2 = false;
					}
				}
				bol1 = bol1 || bol2;
				if (bol2) {
					Ja_copy.remove(i);
					break for2;
				}					
			}
			if (!bol1) {
				tresult.setResult(false);
				tresult.setErrData("接口返回数据:"+o.toString()+"找不到一条包含以下所有参数及其值:"+str+"的数据，");
				break for1;
			}
		}
		return tresult;
	}
	/**
	 * key不包含某值
	 * 示例：notContains(mileage,123)
	 * @param key
	 * @param value
	 * @return Boolean
	 */
	public TResult notContains (String key, String value) {
		Boolean tmp = true;
		 for (Object obj : o) {
			 if (!((JSONObject)obj).containsKey(key)) {
				 Assert.fail("返回数据:"+obj.toString()+"不包含参数:"+key);
			 }
			 if (((JSONObject)obj).getString(key).contains(value)) {
				 tmp = false;
				 tresult.setErrData(obj.toString());
				 break;
			 }
		 }
		tresult.setResult(tmp);
		return tresult;
	}
	/**
	 * 包含key
	 * 示例：containsKey(mileage)
	 * @param key
	 * @return Boolean
	 */
	public TResult containsKey (String key) {
		Boolean tmp = true;
		 for (Object obj : o) {
			 if (!((JSONObject)obj).containsKey(key)) {
				 tmp = false;
				 tresult.setErrData(obj.toString());
				 break;
			 }
		 }
		tresult.setResult(tmp);
		return tresult;
	}
	/**
	 * 不包含key
	 * 示例：notContainsKey(mileage)
	 * @param key
	 * @return Boolean
	 */
	public TResult notContainsKey (String key) {
		Boolean tmp = true;
		 for (Object obj : o) {
			 if (((JSONObject)obj).containsKey(key)) {
				 tmp = false;
				 tresult.setErrData(obj.toString());
				 break;
			 }
		 }
		tresult.setResult(tmp);
		return tresult;
	}
	/**
	 * key值为空
	 * 示例：isNull(mileage)
	 * @param key
	 * @param value
	 * @return Boolean
	 */
	public TResult isNull (String key) {
		Boolean tmp = true;
		 for (Object obj : o) {
			 if (!((JSONObject)obj).containsKey(key)) {
				 Assert.fail("返回数据:"+obj.toString()+"不包含参数:"+key);
			 }
			 if (!InterfaceUtils.isStrEmpty(((JSONObject)obj).getString(key))) {
				 tmp = false;
				 tresult.setErrData(obj.toString());
				 break;
			 }
		 }
		tresult.setResult(tmp);
		return tresult;
	}
	/**
	 * key值非空
	 * 示例：notNull(mileage)
	 * @param key
	 * @param value
	 * @return Boolean
	 */
	public TResult notNull (String key) {
		Boolean tmp = true;
		 for (Object obj : o) {
			 if (!((JSONObject)obj).containsKey(key)) {
				 Assert.fail("返回数据:"+obj.toString()+"不包含参数:"+key);
			 }
			 if (InterfaceUtils.isStrEmpty(((JSONObject)obj).getString(key))) {
				 tmp = false;
				 tresult.setErrData(obj.toString());
				 break;
			 }
		 }
		tresult.setResult(tmp);
		return tresult;
	}
	/**
	 * key等于value
	 * 示例：equals(mileage,123)
	 * @param key
	 * @param value
	 * @return Boolean
	 */
	public TResult equals (String key, String value) {
		Boolean tmp = true;
			 for (Object obj : o) {
				 if (!((JSONObject)obj).containsKey(key)) {
					 Assert.fail("返回数据:"+obj.toString()+"不包含参数:"+key);
				 }
				 if (!((JSONObject)obj).getString(key).equals(value)) {
					 tmp = false;
					 tresult.setErrData(obj.toString());
					 break;
				 }
			 }
		tresult.setResult(tmp);
		return tresult;
	}
	/**
	 * key等于value（忽略大小写）
	 * 示例：equalsIgnorecase(mileage,123)
	 * @param key
	 * @param value
	 * @return Boolean
	 */
	public TResult equalsIgnorecase (String key, String value) {
		Boolean tmp = true;
			 for (Object obj : o) {
				 if (!((JSONObject)obj).containsKey(key)) {
					 Assert.fail("返回数据:"+obj.toString()+"不包含参数:"+key);
				 }
				 if (!((JSONObject)obj).getString(key).equalsIgnoreCase(value)) {
					 tmp = false;
					 tresult.setErrData(obj.toString());
					 break;
				 }
			 }
		tresult.setResult(tmp);
		return tresult;
	}
	/**
	 * 不等于
	 * 示例：notEquals(mileage,123)
	 * @param key
	 * @param value
	 * @return Boolean
	 */
	public TResult notEquals (String key, String value) {
		Boolean tmp = true;
			 for (Object obj : o) {
				 if (!((JSONObject)obj).containsKey(key)) {
					 Assert.fail("返回数据:"+obj.toString()+"不包含参数:"+key);
				 }
				 if (((JSONObject)obj).getString(key).equals(value)) {
					 tmp = false;
					 tresult.setErrData(obj.toString());
					 break;
				 }
			 }
		tresult.setResult(tmp);
		return tresult;
	}
	/**
	 * key值小于
	 * 示例：1:lessThan(time,2015-01-01 00:00:00)或lessThan(time,2015-01-01)或lessThan(time,2015-01-01 00:00)
	 * 2.lessThan(mileage,1234)
	 * @param key
	 * @param value
	 * @return Boolean
	 */
	public TResult lessThan (String key, String value) {
		Boolean tmp = true;
			 for (Object obj : o) {
				 if (!((JSONObject)obj).containsKey(key)) {
					 Assert.fail("返回数据:"+obj.toString()+"不包含参数:"+key);
				 }
				 if (!ObjectCompare.lessThan(((JSONObject)obj).getString(key),value)) {
					 tmp = false;
					 tresult.setErrData(obj.toString());
					 break;
				 }
			 }
		tresult.setResult(tmp);
		return tresult;
	}
	/**
	 * key值大于
	 *  示例：1:greaterThan(time,2015-01-01 00:00:00)或greaterThan(time,2015-01-01)或greaterThan(time,2015-01-01 00:00)
	 * 2.greaterThan(mileage,1234)
	 * @param key
	 * @param value
	 * @return Boolean
	 */
	public TResult greaterThan (String key, String value) {
		Boolean tmp = true;
			 for (Object obj : o) {
				 if (!((JSONObject)obj).containsKey(key)) {
					 Assert.fail("返回数据:"+obj.toString()+"不包含参数:"+key);
				 }
				 if (!ObjectCompare.greaterThan(((JSONObject)obj).getString(key),value)) {
					 tmp = false;
					 tresult.setErrData(obj.toString());
					 break;
				 }
			 }
		tresult.setResult(tmp);
		return tresult;
	}
	/**
	 * key大于等于xxx
	 * 示例：greaterEquals(mileage,123)
	 * @param key
	 * @param value
	 * @return Boolean
	 */
	public TResult greaterEquals (String key, String value) {
		Boolean tmp = true;
			 for (Object obj : o) {
				 if (!((JSONObject)obj).containsKey(key)) {
					 Assert.fail("返回数据:"+obj.toString()+"不包含参数:"+key);
				 }
				 if (!ObjectCompare.greaterThan(((JSONObject)obj).getString(key),value) && !((JSONObject)obj).getString(key).equals(value)) {
					 tmp = false;
					 tresult.setErrData(obj.toString());
					 break;
				 }
			 }
		tresult.setResult(tmp);
		return tresult;
	}
	/**
	 * key小于等于
	 * 示例：lessEquals(mileage,123)
	 * @param key
	 * @param value
	 * @return Boolean
	 */
	public TResult lessEquals (String key, String value) {
		Boolean tmp = true;
			 for (Object obj : o) {
				 if (!((JSONObject)obj).containsKey(key)) {
					 Assert.fail("返回数据:"+obj.toString()+"不包含参数:"+key);
				 }
				 if (!ObjectCompare.lessThan(((JSONObject)obj).getString(key),value) && !((JSONObject)obj).getString(key).equals(value)) {
					 tmp = false;
					 tresult.setErrData(obj.toString());
					 break;
				 }
			 }
		tresult.setResult(tmp);
		return tresult;
	}
	
	/**
	 * 介于value1、value2之间
	 * 示例：between(mileage,123,234)或between(time,2015-01-01,2016-01-01)
	 * @param key
	 * @param value1 比这个值大于或等于
	 * @param value2 比这个值小于或等于
	 * @return Boolean
	 */
	public TResult between (String key, String value1, String value2) {
		TResult tr1 = greaterEquals(key, value1);
		TResult tr2 = greaterEquals(value2,key);
		Boolean bol = tr1.getResult() && tr2.getResult();
		tresult.setResult(bol);
		if (!tr1.getErrData().isEmpty()) {
			tresult.setErrData(tr1.getErrData());
		}
		else if (!tr2.getErrData().isEmpty()) {
			tresult.setErrData(tr2.getErrData());
		}
		return tresult;
	}
	/**
	 * 不介于value1、value2之间
	 * 示例：notBetween(mileage,123,234)或notBetween(time,2015-01-01,2016-01-01)
	 * @param key
	 * @param value1 比这个值大
	 * @param value2 比这个值小
	 * @return Boolean
	 */
	public TResult notBetween (String key, String value1, String value2) {
		TResult tr1 = greaterThan(value1, key);
		TResult tr2 = greaterThan(key,value2);
		Boolean bol = tr1.getResult() || tr2.getResult();
		tresult.setResult(bol);
		if (!tr1.getErrData().isEmpty()) {
			tresult.setErrData(tr1.getErrData());
		}
		else if (!tr2.getErrData().isEmpty()) {
			tresult.setErrData(tr2.getErrData());
		}
		return tresult;
	}
	/**
	 * key值属于某些值中的一个
	 * 示例:in(mileage,"1,2,3")
	 * @param key
	 * @param value
	 * @return Boolean
	 */
	public Boolean in (String key, String value) {
		String valueArr[] = value.split(",");
		Boolean bol = false;
		for (String str : valueArr) {
			bol = bol || equals(key, str).getResult();
		}
		return bol;
	}
	/**
	 * 不属于范围内值中的任何一个
	 * 示例:notIn(mileage,"1,2,3")
	 * @param key
	 * @param value
	 * @return Boolean
	 */
	public Boolean notIn (String key, String value) {
		return !in(key, value);
	}
	/**
	 * key以XXX开头
	 * 示例:startWith(truckno,adc)
	 * @param key
	 * @param value
	 * @return Boolean
	 */
	public TResult startWith (String key, String value) {
		Boolean tmp = true;
			 for (Object obj : o) {
				 if (!((JSONObject)obj).containsKey(key)) {
					 Assert.fail("返回数据:"+obj.toString()+"不包含参数:"+key);
				 }
				 if (!((JSONObject)obj).getString(key).startsWith(value)) {
					 tmp = false;
					 tresult.setErrData(obj.toString());
					 break;
				 }
			 }
		tresult.setResult(tmp);
		return tresult;
	}
	/**
	 * key以XXX结尾
	 * 示例:endWith(truckno,adc)
	 * @param key
	 * @param value
	 * @return Boolean
	 */
	public TResult endWith (String key, String value) {
		Boolean tmp = true;
			 for (Object obj : o) {
				 if (!((JSONObject)obj).containsKey(key)) {
					 Assert.fail("返回数据:"+obj.toString()+"不包含参数:"+key);
				 }
				 if (!((JSONObject)obj).getString(key).endsWith(value)) {
					 tmp = false;
					 tresult.setErrData(obj.toString());
					 break;
				 }
			 }
		tresult.setResult(tmp);
		return tresult;
	}
	/**
	 * 按顺序依次检查每条数据时间间隔是否不超过value秒/按顺序依次检查每条数据某key的值相差是否超过value,(只支持jsonArray)
	 * 示例：1.dataDifCheck(time,10)  意思每条数据时间间隔不超过10s
	 * 2.dataDifCheck(mileage,10) 按顺序每条数据里程值差不超过10
	 * @param key
	 * @param value 如果比较时间：单位为s
	 * @return Boolean
	 */
	public Boolean dataDifCheck(String key, String value) {
		return dataDifCheck(key, value, "yyyy-MM-dd HH:mm:ss");
	}
	
	/**
	 * 相邻数据差值检查 ,时间格式自定义(只支持jsonArray)
	 * 示例:dataDifCheck(time,10,yyyy-MM-dd)
	 * @param key
	 * @param value 如果比较时间：单位为s
	 * @param timestamp 时间格式
	 * @return 
	 * @return Boolean
	 */
	public Boolean dataDifCheck(String key, String value, String timestamp) {
		Boolean bol = true;
		if (!((JSONObject)o.get(0)).containsKey(key)) {
			 Assert.fail("返回数据:"+((JSONObject)o.get(0)).toString()+"不包含参数:"+key);
		 }
		String str = ((JSONObject)o.get(0)).getString(key);
		if (InterfaceUtils.isValidDate(str, timestamp)) {
			for (int i = 1; i < o.size(); i++) {
				if (!((JSONObject)o.get(i)).containsKey(key)) {
					 Assert.fail("返回数据:"+((JSONObject)o.get(i)).toString()+"不包含参数:"+key);
				 }
				long dif = InterfaceUtils.getTimeDif(str, ((JSONObject)o.get(i)).getString(key), timestamp);
				str = ((JSONObject)o.get(i)).getString(key);
				if (Long.parseLong(value) > dif) {
					bol = false;
//					Assert.fail("返回结果中第"+(i+1)+"条数据与第"+i+"条数据参数"+ key + "的差值小于预期"+value+"，该测试失败");
					break;
				}
			}
		}		
		else {
			for (int i = 1; i < o.size(); i++) {
				if (!((JSONObject)o.get(i)).containsKey(key)) {
					 Assert.fail("返回数据:"+((JSONObject)o.get(i)).toString()+"不包含参数:"+key);
				 }
				Double dif = Math.abs(Double.parseDouble(((JSONObject)o.get(i)).getString(key)) - Double.parseDouble(str));
				str = ((JSONObject)o.get(i)).getString(key);
				if (Double.parseDouble(value) > dif) {
					bol = false;
//					Assert.fail("返回结果中第"+(i+1)+"条数据与第"+i+"条数据参数"+ key + "的差值小于预期"+value+"，该测试失败");
					break;
				}
			}
		}
		return bol;
	}
	/**
	 * 返回的data中key是否包含所有值(只支持jsonArray)
	 * 示例:containsAll(mileage,"100,200,300")
	 * @param key 
	 * @param value 要包含的值，以"，"间隔
	 * @return Boolean
	 */
	public Boolean containsAll (String key, String value) {
		String [] valueArr = value.split(",");
		Set<String> l1 = new HashSet<String>(Arrays.asList(valueArr));;
		Set<String> l2 = new HashSet<String>();
		String str;
		for (int i = 0; i < o.size(); i++) {
			if (!((JSONObject)o.get(i)).containsKey(key)) {
				 Assert.fail("返回数据:"+((JSONObject)o.get(i)).toString()+"不包含参数:"+key);
			}
			str = ((JSONObject)o.get(i)).getString(key);
			l2.add(str);
		}		
		return l2.containsAll(l1);
	}
	
	/**
	 * 返回的data中key是否包含并且只包含这些值(只支持jsonArray)
	 * 示例:onlyContainsAll(mileage,"100,200,300")
	 * @param key 
	 * @param value 要包含的值，以"，"间隔
	 * @return Boolean
	 */
	public Boolean onlyContainsAll (String key, String value) {
		String [] valueArr = value.split(",");
		Set<String> l1 = new HashSet<String>(Arrays.asList(valueArr));;
		Set<String> l2 = new HashSet<String>();
		String str;
		for (int i = 0; i < o.size(); i++) {
			if (!((JSONObject)o.get(i)).containsKey(key)) {
				 Assert.fail("返回数据:"+((JSONObject)o.get(i)).toString()+"不包含参数:"+key);
			}
			str = ((JSONObject)o.get(i)).getString(key);
			l2.add(str);
		}		
		return l2.containsAll(l1) && l1.containsAll(l2);
	}
	/**
	 * 判断返回数据是否有重复数据 (只支持jsonArray)
	 * 示例:noRepeatedData()
	 * @return Boolean
	 */
	public Boolean noRepeatedData () {
		Set<String> set = new HashSet<String>();
		String str;
		for (int i = 0; i < o.size(); i++) {
			str = ((JSONObject)o.get(i)).toJSONString();
			set.add(str);
		}	
		if (o.size() == set.size()) {
			return true;
		}
		else {
			return false;
		}
	}
	/**
	 * 判断json数组中每个jsonObject的key值是否递增
	 * @param key
	 * @return Boolean
	 */
	public Boolean valueIncrease (String key) {
		String value;
		Boolean bol = true;
		String tmpvalue = null;
		for (int i = 0; i < o.size(); i++) {
			if (!((JSONObject)o.get(i)).containsKey(key)) {
				 Assert.fail("返回数据:"+((JSONObject)o.get(i)).toString()+"不包含参数:"+key);
			}
			value = ((JSONObject)o.get(i)).getString(key);
			if (i > 0) {
				bol &= ObjectCompare.greaterThan(value, tmpvalue);
			}
			tmpvalue = value;
		}
		return bol;
	}
	/**
	 * 判断json数组中每个jsonObject的key值是否递减
	 * @param key
	 * @return Boolean
	 */
	public Boolean valueDecrease (String key) {
		String value;
		Boolean bol = true;
		String tmpvalue = null;
		for (int i = 0; i < o.size(); i++) {
			if (!((JSONObject)o.get(i)).containsKey(key)) {
				 Assert.fail("返回数据:"+((JSONObject)o.get(i)).toString()+"不包含参数:"+key);
			}
			value = ((JSONObject)o.get(i)).getString(key);
			if (i > 0) {
				bol &= ObjectCompare.lessThan(value, tmpvalue);
			}
			tmpvalue = value;
		}
		return bol;	
	}
}